<?php

namespace Modules\Wechat\Model\Data;

/**
 * 微信模块数据逻辑层抽象类
 *
 * @package Modules\Wechat\Data
 */
abstract class Abstraction
{

    const STATUS_NORMAL  = 0;
    const STATUS_DELETED = 50;
    const STATUS_ANY     = null;

    const DICT_SCOPE_STATUS = 'status';

    const DICT_ENTRY_ID          = 'id';
    const DICT_ENTRY_VALUE       = 'val';
    const DICT_ENTRY_EXPLANATION = 'exp';

    const DICT_ENTRY_VALUE_DEFAULT = '';

    const DICT_SCOPE_MSG_TYPE  = 'msg_type';
    const MSG_TYPE_TEXT        = 'text';
    const MSG_TYPE_IMAGE       = 'image';
    const MSG_TYPE_VOICE       = 'voice';
    const MSG_TYPE_VIDEO       = 'video';
    const MSG_TYPE_SHORT_VIDEO = 'shortvideo';
    const MSG_TYPE_LOCATION    = 'location';
    const MSG_TYPE_LINK        = 'link';
    const MSG_TYPE_EVENT       = 'event';

    const DICT_SCOPE_MSG_EVENT  = 'msg_event';
    const MSG_EVENT_SUBSCRIBE   = 'subscribe';
    const MSG_EVENT_UNSUBSCRIBE = 'unsubscribe';
    const MSG_EVENT_SCAN        = 'scan';
    const MSG_EVENT_LOCATION    = 'location';
    const MSG_EVENT_CLICK       = 'click';
    const MSG_EVENT_VIEW        = 'view';


    protected static $dictionaries           = [];
    protected static $dictionary_initialized = false;
    protected static $dictionary_maps        = [];

    protected static $_dictionaries = [
        self::DICT_SCOPE_STATUS    => [
            [self::DICT_ENTRY_ID => self::STATUS_NORMAL, self::DICT_ENTRY_VALUE => '正常'],
            [self::DICT_ENTRY_ID => self::STATUS_DELETED, self::DICT_ENTRY_VALUE => '已删除'],
        ],
        self::DICT_SCOPE_MSG_TYPE  => [
            [self::DICT_ENTRY_ID => self::MSG_TYPE_TEXT, self::DICT_ENTRY_VALUE => '文本消息'],
            [self::DICT_ENTRY_ID => self::MSG_TYPE_IMAGE, self::DICT_ENTRY_VALUE => '图片消息'],
            [self::DICT_ENTRY_ID => self::MSG_TYPE_VOICE, self::DICT_ENTRY_VALUE => '语音消息'],
            [self::DICT_ENTRY_ID => self::MSG_TYPE_VIDEO, self::DICT_ENTRY_VALUE => '视频消息'],
            [self::DICT_ENTRY_ID => self::MSG_TYPE_SHORT_VIDEO, self::DICT_ENTRY_VALUE => '小视频消息'],
            [self::DICT_ENTRY_ID => self::MSG_TYPE_LOCATION, self::DICT_ENTRY_VALUE => '地理位置消息'],
            [self::DICT_ENTRY_ID => self::MSG_TYPE_LINK, self::DICT_ENTRY_VALUE => '链接消息'],
            [self::DICT_ENTRY_ID => self::MSG_TYPE_EVENT, self::DICT_ENTRY_VALUE => '事件消息'],
        ],
        self::DICT_SCOPE_MSG_EVENT => [
            [self::DICT_ENTRY_ID => self::MSG_EVENT_SUBSCRIBE, self::DICT_ENTRY_VALUE => '订阅'],
            [self::DICT_ENTRY_ID => self::MSG_EVENT_UNSUBSCRIBE, self::DICT_ENTRY_VALUE => '取消订阅'],
            [self::DICT_ENTRY_ID => self::MSG_EVENT_SCAN, self::DICT_ENTRY_VALUE => '扫描带参数二维码'],
            [self::DICT_ENTRY_ID => self::MSG_EVENT_LOCATION, self::DICT_ENTRY_VALUE => '上报地理位置'],
            [self::DICT_ENTRY_ID => self::MSG_EVENT_CLICK, self::DICT_ENTRY_VALUE => '自定义菜单'],
            [self::DICT_ENTRY_ID => self::MSG_EVENT_VIEW, self::DICT_ENTRY_VALUE => '点击菜单跳转链接'],
        ],
    ];


    final public function __construct()
    {
        $this->init();
    }

    abstract protected function init();

    protected static function isDictionaryInitialized()
    {
        return self::$dictionary_initialized;
    }

    protected static function setDictionaryInitialized($dictionary_initialized)
    {
        self::$dictionary_initialized = $dictionary_initialized;
    }

    protected static function setDictionary($scope, array $entries = [], $overwrite = false)
    {
        if (array_key_exists($scope, static::$_dictionaries)) {
            static::$_dictionaries[$scope] = $overwrite
                ? $entries
                : array_merge(static::$_dictionaries[$scope], $entries);
        } else {
            static::$_dictionaries[$scope] = $entries;
        }
        return $entries;
    }

    protected static function setDictionaries(array $dictionaries, $overwrite = false)
    {
        foreach ($dictionaries as $scope => $entries) {
            self::setDictionary($scope, $entries, $overwrite);
        }
        return $dictionaries;
    }


    protected static function dictGetList($scope, $default = [])
    {
        if (!static::isDictionaryInitialized()) {
            static::setDictionaries(static::$dictionaries);
            static::setDictionaryInitialized(true);
        }
        return array_key_exists($scope, static::$_dictionaries)
            ? static::$_dictionaries[$scope]
            : $default;
    }

    protected static function dictGetMap($scope, $default = [])
    {
        if (!array_key_exists($scope, self::$dictionary_maps)) {
            self::$dictionary_maps[$scope] = [];
            foreach (static::dictGetList($scope, []) as $entry) {
                self::$dictionary_maps[$scope][$entry[static::DICT_ENTRY_ID]] = $entry[static::DICT_ENTRY_VALUE];
            }
        }
        return self::$dictionary_maps[$scope] ?: $default;
    }

    protected static function dictGetEntryIdByName($scope, $entry_name, $default = '')
    {
        $id = array_search($entry_name, static::dictGetMap($scope, []));
        return false === $id ? $default : $id;
    }

    protected static function dictGetEntryNameById($scope, $entry_id, $default = '0')
    {
        $map = static::dictGetMap($scope, []);
        return array_key_exists($entry_id, $map) ? $map[$entry_id] : $default;
    }

    public static function getStatusName($status)
    {
        return static::dictGetEntryNameById(static::DICT_SCOPE_STATUS, $status);
    }

    public static function getStatusList()
    {
        return static::dictGetList(static::DICT_SCOPE_STATUS, []);
    }

    public static function getMsgTypeName($type)
    {
        return static::dictGetEntryNameById(static::DICT_SCOPE_MSG_TYPE, $type);
    }

    public static function getMsgEventName($event)
    {
        return static::dictGetEntryNameById(static::DICT_SCOPE_MSG_EVENT, $event);
    }

}